﻿/*
 * comdevice.cpp
 *
 *  Created on: 2017年2月7日
 *      Author: work
 */

#include <dm/export.hpp>

#define DM_API_OS_COM DM_API_EXPORT

#include <dm/os/com/device.hpp>
#include <dm/os/log/logger.hpp>
#include <boost/system/error_code.hpp>

namespace dm{
namespace os{
namespace com{

static const char* logModule = "CDevice.com.os.dm";

CDevice::CDevice( const size_t& rxBufSize ):
		m_state(Unconnected),m_rxBufSize(rxBufSize),m_addr(){
	if( rxBufSize>0 )
		m_rxBuf.reset(new dm::uint8[rxBufSize]);
	log().debug( THISMODULE "初始化通信设备rxBuf%d",rxBufSize);
}

CDevice::~CDevice(){
	log().debug(THISMODULE "释放通信设备");
}

bool CDevice::setAddress( const CAddress& addr ){
	if( m_state!=Unconnected )
		return false;
	switch( addr.getType() ){
	case CAddress::SerialPort:
		if( addr.asSerialPort()!=NULL )
			return checkAndSetAddress( *addr.asSerialPort() );
		break;

	case CAddress::TcpClient:
		if( addr.asTcpClient()!=NULL )
			return checkAndSetAddress( *addr.asTcpClient() );
		break;
	case CAddress::TcpBindClient:
		if( addr.asTcpBindClient()!=NULL )
			return checkAndSetAddress( *addr.asTcpBindClient() );
		break;
	case CAddress::TcpServer:
		if( addr.asTcpServer()!=NULL )
			return checkAndSetAddress( *addr.asTcpServer() );
		break;
	case CAddress::TcpConnect:
		if( addr.asTcpConnect()!=NULL )
			return checkAndSetAddress( *addr.asTcpConnect() );
		break;

	case CAddress::UdpClient:
		if( addr.asUdpClient()!=NULL )
			return checkAndSetAddress( *addr.asUdpClient() );
		break;
	case CAddress::UdpBindClient:
		if( addr.asUdpBindClient()!=NULL )
			return checkAndSetAddress( *addr.asUdpBindClient() );
		break;
	case CAddress::UdpServer:
		if( addr.asUdpServer()!=NULL )
			return checkAndSetAddress( *addr.asUdpServer() );
		break;
	case CAddress::UdpConnect:
		if( addr.asUdpConnect()!=NULL )
			return checkAndSetAddress( *addr.asUdpConnect() );
		break;

	case CAddress::Can:
		if( addr.asCan()!=NULL )
			return checkAndSetAddress( *addr.asCan() );
		break;
	default:
		break;
	}

	return false;
}

bool CDevice::checkAndSetAddress( const CSerialAddr& ){
	return false;
}

bool CDevice::checkAndSetAddress( const CTcpClientAddr& ){
	return false;
}

bool CDevice::checkAndSetAddress( const CTcpServerAddr& ){
	return false;
}

bool CDevice::checkAndSetAddress( const CTcpBindClientAddr& ){
	return false;
}

bool CDevice::checkAndSetAddress( const CTcpConnectAddr& ){
	return false;
}

bool CDevice::checkAndSetAddress( const CUdpClientAddr& ){
	return false;
}

bool CDevice::checkAndSetAddress( const CUdpServerAddr& ){
	return false;
}

bool CDevice::checkAndSetAddress( const CUdpBindClientAddr& ){
	return false;
}

bool CDevice::checkAndSetAddress( const CUdpConnectAddr& ){
	return false;
}

bool CDevice::checkAndSetAddress( const CCanAddr& ){
	return false;
}

/**
 * 异步启动连接
 * @return
 */
bool CDevice::asynConnect(){
	if( m_state==Unconnected ){
		m_state = Connecting;
		if( startConnect() ){
			return true;
		}else{
			log().debug( THISMODULE "打开设备失败");
			m_state = Unconnected;
		}
	}else
		log().debug( THISMODULE "当前状态不允许");

	return false;
}

/**
 * 请求停止
 * @return
 */
bool CDevice::asynDisconnect(){
	if( m_state!=Connected ){
		log().debug( THISMODULE "当前状态不允许");
		return false;
	}

	if( stopConnect() ){
		m_state = Disconnecting;
		return true;
	}else{
		log().info( THISMODULE "停止连接失败");
		return false;
	}
}

/**
 * 请求发送数据
 * @param buf
 * @param len
 * @return
 */
bool CDevice::asynSend( const dm::uint8* buf,const size_t& len ){
	if( m_state!=Connected ){
		log().warnning(THISMODULE "当前未连接或正忙，不允许发送");
		return false;
	}

	if( startSend(buf,len) ){
		m_state = Sending;
		return true;
	}else{
		log().warnning(THISMODULE "启动发送失败");
		return false;
	}
}

void CDevice::handler_connect( const error_t& ec ){
	if( ec==boost::system::errc::connection_aborted ){
		// 被取消
		m_state = Unconnected;
	}else	if( ec ){
		log().warnning(THISMODULE "启动连接失败");
		m_state = Unconnected;
		onConnectFail();
	}else{
		m_state = Connected;
		onConnected();
	}
}

void CDevice::handler_disconnect( const error_t& ec ){
	if( ec ){
		m_state = Error;
		onDisconnectFail();
	}else{
		m_state = Unconnected;
//		cancelDev();
		onDisconnected();
	}
}

void CDevice::handler_tx( const boost::system::error_code& ec ){
	if( ec==boost::system::errc::connection_aborted ){
		// 被取消
	}else if( ec ){
		log().warnning(THISMODULE "tx fail(%s)",ec.message().c_str());
		m_state = Error;
		onSendFail();
	}else{
		m_state = Connected;
		onSendSuccess();
	}
}

void CDevice::handler_rx( const boost::system::error_code& ec,size_t transferred ){
	if( ec==boost::system::errc::connection_aborted ){
		// 被取消
		log().info(THISMODULE "被取消");
	}else	if( ec ){
		log().warnning(THISMODULE "rx fail(%s)",ec.message().c_str());
		m_state = Error;
		onReceiveFail();
	}else{
		onReceived( m_rxBuf.get(),transferred);
		start_rx();
	}
}

bool CDevice::onConnected(){
	start_rx();
	return true;
}

void CDevice::onConnectFail(){
	log().warnning(THISMODULE "do nothing");
}

void CDevice::onReceived( const dm::uint8*,const size_t& ){
	log().warnning(THISMODULE "do nothing");
}

void CDevice::onSendSuccess(){
	log().warnning( THISMODULE "do nothing");
}

void CDevice::onReceiveFail(){
	log().warnning( THISMODULE "do nothing");
}

void CDevice::onSendFail(){
	log().warnning( THISMODULE "do nothing");
}

void CDevice::onDisconnected(){
	log().warnning(THISMODULE "do nothing");
}

void CDevice::onDisconnectFail(){
	log().warnning(THISMODULE "do nothing");
}

bool CDevice::startConnect(){
	log().warnning(THISMODULE "禁止连接");
	return false;
}

bool CDevice::stopConnect(){
	log().warnning(THISMODULE "禁止关闭");
	return false;
}

bool CDevice::startSend( const dm::uint8*,const size_t& ){
	log().warnning(THISMODULE "不允许发送数据");
	return false;
}

}
}
}


